install & setup

https://tensorflow.rstudio.com

https://github.com/rstudio/tensorflow

# 下载R tensorflow包
# devtools::install_github("rstudio/tensorflow")
# library(tensorflow)
# 如果没有安装好tensorflow的环境,可以通过以下命令安装
# tensorflow::install_tensorflow(
#   method = "conda",
#   conda = "/opt/homebrew/Caskroom/miniforge/base/bin",
#   envname = "r-reticulate"
#   )
# library(reticulate)
# 启用安装好tensorflow的conda环境
reticulate::use_condaenv(
  condaenv = "r-reticulate",
  conda = "/opt/homebrew/Caskroom/miniforge",
  required = TRUE
)
# 查看当前conda环境配置
reticulate::py_config()
## python:         /opt/homebrew/Caskroom/miniforge/base/envs/r-reticulate/bin/python
## libpython:      /opt/homebrew/Caskroom/miniforge/base/envs/r-reticulate/lib/libpython3.9.dylib
## pythonhome:     /opt/homebrew/Caskroom/miniforge/base/envs/r-reticulate:/opt/homebrew/Caskroom/miniforge/base/envs/r-reticulate
## version:        3.9.6 | packaged by conda-forge | (default, Jul 11 2021, 03:35:11)  [Clang 11.1.0 ]
## numpy:          /opt/homebrew/Caskroom/miniforge/base/envs/r-reticulate/lib/python3.9/site-packages/numpy
## numpy_version:  1.19.5
## 
## NOTE: Python version was forced by RETICULATE_PYTHON

params config

# 图片像素
size <- 128
# 验证集比例
valid_size <- 0.1
# 随机数种子
seed <- 1234
# 批次大小
batch_size <- 32

generate model

# 加载tensorflowAPI:Keras
library(keras)

# 加载resnet50预训练模型
base_model <- application_resnet50(include_top=F, weights='imagenet', classes=2,
                                   input_shape = c(size, size, 3))
# 冻结预训练模型
for (layes in base_model$layers)
  layes$trainable <- F

# 添加池化层和全连接层
model <- keras_model_sequential() %>% 
  base_model %>%
  layer_average_pooling_2d() %>%
  layer_flatten() %>%
  layer_dropout(rate = 0.2) %>%
  layer_dense(2, activation = 'softmax')

# 展示模型结构
summary(model)
## Model: "sequential"
## ________________________________________________________________________________
## Layer (type)                        Output Shape                    Param #     
## ================================================================================
## resnet50 (Functional)               (None, 4, 4, 2048)              23587712    
## ________________________________________________________________________________
## average_pooling2d (AveragePooling2D (None, 2, 2, 2048)              0           
## ________________________________________________________________________________
## flatten (Flatten)                   (None, 8192)                    0           
## ________________________________________________________________________________
## dropout (Dropout)                   (None, 8192)                    0           
## ________________________________________________________________________________
## dense (Dense)                       (None, 2)                       16386       
## ================================================================================
## Total params: 23,604,098
## Trainable params: 16,386
## Non-trainable params: 23,587,712
## ________________________________________________________________________________
# 设置优化器、损失函数和评估函数
model %>% compile(
  optimizer = 'Adam',
  loss = 'categorical_crossentropy',
  metrics = "accuracy"
)

data generator

https://www.kaggle.com/c/dogs-vs-cats/data

setwd("~/Desktop/算法/深度学习/dogs-vs-cats")

# 构建图像数据生成器,并做数据增强
image_generator <-image_data_generator(
  validation_split = valid_size, # 验证集比例
  # rotation_range = 30, # 旋转范围
  # width_shift_range = 0.1, # 横向平移范围
  # height_shift_range = 0.1, # 纵向平移范围
  # zoom_range = 0.1, # 放缩范围
  rescale = 1/255 # 将像素值转为0-1
)

# 构建训练及验证数据生成器
train_data_generator <- flow_images_from_directory(
  directory = "dogs-vs-cats/train_2class/", 
  generator = image_generator,
  target_size = c(size, size),
  batch_size = batch_size,
  interpolation = "bicubic",
  subset = "training",
  shuffle = TRUE,
  seed = seed
)
valid_data_generator <- flow_images_from_directory(
  directory = "dogs-vs-cats/train_2class/", 
  generator = image_generator,
  target_size = c(size, size),
  batch_size = batch_size,
  interpolation = "bicubic",
  subset = "validation",
  shuffle = TRUE,
  seed = seed
)

train

model %>% fit_generator(
  generator = train_data_generator,
  steps_per_epoch = 1, # floor(25000*(1-valid_size)/batch_size),
  epochs = 1,
  validation_data = valid_data_generator,
  validation_steps = 1
)

# model %>% save_model_hdf5("ResNet50")

evaluate

model %>% load_model_weights_hdf5("ResNet50")
model %>% evaluate_generator(
  generator = valid_data_generator,
  steps = 10
)
##      loss  accuracy 
## 0.2537442 0.9312500

inference

# 画图函数
img_plot <- function(file){
  img <- EBImage::readImage(file)
  EBImage::display(img)
}
# 推理函数
inference <- function(file, size = 128){
  img_plot(file)
  img <- keras::image_load(file, target_size = c(size, size),
                              interpolation = "bicubic")
  x <- keras::image_to_array(img)
  x <- x / 255
  x <- reticulate::array_reshape(x[, , 1:3], c(1, size, size, 3))
  is_dog <- model %>% 
    predict(x) %>% 
    k_argmax()
  is_dog_str <- ifelse(is_dog, 'dog', 'cat')
  print(is_dog_str)
}
# 载入训练好的模型进行推理
# model %>% load_model_weights_hdf5("ResNet50")
setwd("./试试看")
for(pic in list.files("./"))
  inference(pic)

## [1] "dog"

## [1] "dog"

## [1] "cat"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "cat"

## [1] "cat"

## [1] "cat"

## [1] "cat"

## [1] "cat"

## [1] "cat"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "cat"

## [1] "cat"

## [1] "cat"

## [1] "cat"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "cat"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "dog"

## [1] "dog"
# img_plot("胖虎4.jpeg")
# inference("胖虎4.jpeg")